/*
 * SeamCarvingFrame.java
 *
 * Created on 30. August 2007, 16:04
 */

package net.semanticmetadata.seams;

import javax.swing.*;
import javax.swing.filechooser.FileNameExtensionFilter;
import javax.imageio.ImageIO;
import java.io.IOException;

/**
 * @author mlux
 */
public class SeamCarvingFrame extends javax.swing.JFrame {

    /**
     * Creates new form SeamCarvingFrame
     */
    public SeamCarvingFrame() {
        initComponents();
    }

    /**
     * This method is called from within the constructor to
     * initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is
     * always regenerated by the Form Editor.
     */
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {

        toolBar = new javax.swing.JToolBar();
        buttonOpenFile = new javax.swing.JButton();
        buttonProcess = new javax.swing.JButton();
        buttonSaveFile = new javax.swing.JButton();
        jSeparator1 = new javax.swing.JToolBar.Separator();
        buttonExit = new javax.swing.JButton();
        jSeparator2 = new javax.swing.JToolBar.Separator();
        helpButton = new javax.swing.JButton();
        heightSpinner = new javax.swing.JSpinner();
        widthSpinner = new javax.swing.JSpinner();
        jLabel1 = new javax.swing.JLabel();
        jLabel2 = new javax.swing.JLabel();
        brushSizeSlider = new javax.swing.JSlider();
        jLabel3 = new javax.swing.JLabel();
        brushSizeLabel = new javax.swing.JLabel();
        removeCheckBox = new javax.swing.JCheckBox();
        jScrollPane1 = new javax.swing.JScrollPane();
        imagePanel = new net.semanticmetadata.seams.ImageViewPanel();

        setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
        setTitle("SeamCarving (v4) by Mathias Lux");

        toolBar.setRollover(true);
        toolBar.setEnabled(false);

        buttonOpenFile.setIcon(new javax.swing.ImageIcon(getClass().getResource("/resources/fileopen.png"))); // NOI18N
        buttonOpenFile.setToolTipText("Open image");
        buttonOpenFile.setFocusable(false);
        buttonOpenFile.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER);
        buttonOpenFile.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM);
        buttonOpenFile.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                buttonOpenFileActionPerformed(evt);
            }
        });
        toolBar.add(buttonOpenFile);

        buttonProcess.setIcon(new javax.swing.ImageIcon(getClass().getResource("/resources/exec.png"))); // NOI18N
        buttonProcess.setToolTipText("Resize image");
        buttonProcess.setFocusable(false);
        buttonProcess.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER);
        buttonProcess.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM);
        buttonProcess.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                buttonProcessActionPerformed(evt);
            }
        });
        toolBar.add(buttonProcess);

        buttonSaveFile.setIcon(new javax.swing.ImageIcon(getClass().getResource("/resources/filesave.png"))); // NOI18N
        buttonSaveFile.setToolTipText("Save result");
        buttonSaveFile.setFocusable(false);
        buttonSaveFile.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER);
        buttonSaveFile.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM);
        buttonSaveFile.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                buttonSaveFileActionPerformed(evt);
            }
        });
        toolBar.add(buttonSaveFile);
        toolBar.add(jSeparator1);

        buttonExit.setIcon(new javax.swing.ImageIcon(getClass().getResource("/resources/exit.png"))); // NOI18N
        buttonExit.setToolTipText("Close application");
        buttonExit.setFocusable(false);
        buttonExit.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER);
        buttonExit.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM);
        buttonExit.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                buttonExitActionPerformed(evt);
            }
        });
        toolBar.add(buttonExit);

        jSeparator2.setPreferredSize(new java.awt.Dimension(3, 2));
        toolBar.add(jSeparator2);

        helpButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/resources/help.png"))); // NOI18N
        helpButton.setFocusable(false);
        helpButton.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER);
        helpButton.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM);
        helpButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                showHelp(evt);
            }
        });
        toolBar.add(helpButton);

        jLabel1.setText("Width:");

        jLabel2.setText("Height:");

        brushSizeSlider.setMinimum(5);
        brushSizeSlider.setPaintLabels(true);
        brushSizeSlider.setValue(30);
        brushSizeSlider.addChangeListener(new javax.swing.event.ChangeListener() {
            public void stateChanged(javax.swing.event.ChangeEvent evt) {
                brushSizeSliderStateChanged(evt);
            }
        });

        jLabel3.setText("Brush size:");

        brushSizeLabel.setText("25");

        removeCheckBox.setText("remove");
        removeCheckBox.setBorder(javax.swing.BorderFactory.createEmptyBorder(0, 0, 0, 0));
        removeCheckBox.addChangeListener(new javax.swing.event.ChangeListener() {
            public void stateChanged(javax.swing.event.ChangeEvent evt) {
                removeCheckBoxStateChanged(evt);
            }
        });

        javax.swing.GroupLayout imagePanelLayout = new javax.swing.GroupLayout(imagePanel);
        imagePanel.setLayout(imagePanelLayout);
        imagePanelLayout.setHorizontalGroup(
            imagePanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGap(0, 648, Short.MAX_VALUE)
        );
        imagePanelLayout.setVerticalGroup(
            imagePanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGap(0, 355, Short.MAX_VALUE)
        );

        jScrollPane1.setViewportView(imagePanel);

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
        getContentPane().setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addComponent(toolBar, javax.swing.GroupLayout.DEFAULT_SIZE, 650, Short.MAX_VALUE)
            .addGroup(layout.createSequentialGroup()
                .addContainerGap()
                .addComponent(jLabel1)
                .addGap(6, 6, 6)
                .addComponent(widthSpinner, javax.swing.GroupLayout.PREFERRED_SIZE, 72, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(jLabel2)
                .addGap(3, 3, 3)
                .addComponent(heightSpinner, javax.swing.GroupLayout.PREFERRED_SIZE, 64, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addGap(9, 9, 9)
                .addComponent(jLabel3)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(brushSizeSlider, javax.swing.GroupLayout.PREFERRED_SIZE, 65, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(brushSizeLabel)
                .addGap(18, 18, 18)
                .addComponent(removeCheckBox)
                .addContainerGap(123, Short.MAX_VALUE))
            .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 650, Short.MAX_VALUE)
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addComponent(toolBar, javax.swing.GroupLayout.PREFERRED_SIZE, 25, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addGap(11, 11, 11)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.CENTER)
                    .addComponent(removeCheckBox)
                    .addComponent(brushSizeLabel)
                    .addComponent(jLabel3)
                    .addComponent(heightSpinner, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(jLabel2)
                    .addComponent(jLabel1)
                    .addComponent(brushSizeSlider, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(widthSpinner, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 345, Short.MAX_VALUE))
        );

        pack();
    }// </editor-fold>//GEN-END:initComponents

private void removeCheckBoxStateChanged(javax.swing.event.ChangeEvent evt) {//GEN-FIRST:event_removeCheckBoxStateChanged
    imagePanel.enableRemoveBrush(removeCheckBox.isSelected());
}//GEN-LAST:event_removeCheckBoxStateChanged

private void buttonExitActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_buttonExitActionPerformed
    int i = JOptionPane.showConfirmDialog(this, "Do you really want to quit?", "Quit?", JOptionPane.YES_NO_OPTION);
    if (i == JOptionPane.OK_OPTION) System.exit(0);
}//GEN-LAST:event_buttonExitActionPerformed

private void buttonSaveFileActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_buttonSaveFileActionPerformed
    JFileChooser jfc = new JFileChooser(".");
    jfc.setFileFilter(new FileNameExtensionFilter("PNG images", "png"));
    int i = jfc.showSaveDialog(this);
    if (i== JFileChooser.APPROVE_OPTION) {
        try {
            ImageIO.write(imagePanel.getImg(), "png", jfc.getSelectedFile());
        } catch (IOException e) {
            JOptionPane.showMessageDialog(this, "Error saving file: " + e.toString(), "Error", JOptionPane.ERROR_MESSAGE);
        }
    }
}//GEN-LAST:event_buttonSaveFileActionPerformed

private void brushSizeSliderStateChanged(javax.swing.event.ChangeEvent evt) {//GEN-FIRST:event_brushSizeSliderStateChanged
    imagePanel.setBrushSize(brushSizeSlider.getValue());
    brushSizeLabel.setText(brushSizeSlider.getValue() + "");
}//GEN-LAST:event_brushSizeSliderStateChanged

private void buttonProcessActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButton1ActionPerformed
    final ImageSeamOperations s = new ImageSeamOperations(imagePanel.getImg(), imagePanel.getOverlay());
    int nw = ((Number) widthSpinner.getModel().getValue()).intValue();
    int nh = ((Number) heightSpinner.getModel().getValue()).intValue();
    final int fnw = s.getImg().getWidth() - nw;
    final int fnh = s.getImg().getHeight() - nh;
    if (fnw >=0 && fnw <s.getImg().getWidth() && fnh >=0 && fnh <s.getImg().getHeight()) {
        Thread t = new Thread(new Runnable() {
            public void run() {
                toolBar.setEnabled(false);
                int h = fnh, w=fnw;
                for (int i = 0; i< Math.max(fnh, fnw); i++) {
                    if (h>0) {
                        s.carveHorizontalSeam();
                        h--;
                    }
                    if (w>0) {
                        s.carveVerticalSeam();
                        w--;
                    }
                    if ((h+w)%5==0) imagePanel.setImageWithViewUpdate(s.getImg());
                    else imagePanel.setImage(s.getImg());
                }
                imagePanel.setImageWithViewUpdate(s.getImg());
                toolBar.setEnabled(true);
            }
        });
        t.start();
    } else {
        JOptionPane.showMessageDialog(this, "Error: New width/height not supported (only shrinking)");
    }
}//GEN-LAST:event_jButton1ActionPerformed

    private void buttonOpenFileActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_buttonOpenFileActionPerformed
        JFileChooser jfc = new JFileChooser(".");
        jfc.setFileFilter(new FileNameExtensionFilter("Images", "png", "jpg"));
        int i = jfc.showOpenDialog(this);
        if (i == JFileChooser.APPROVE_OPTION) {
            try {
                imagePanel.setImageWithViewUpdate(ImageIO.read(jfc.getSelectedFile()));
                // widthSpinner.setimagePanel.getImg().getWidth();
                widthSpinner.getModel().setValue(imagePanel.getImg().getWidth());
                heightSpinner.getModel().setValue(imagePanel.getImg().getHeight());
            } catch (IOException e) {
                JOptionPane.showInternalMessageDialog(this, "Error loading image: " + e.toString(), "Error loading image", JOptionPane.ERROR_MESSAGE);
            }
        }
    }//GEN-LAST:event_buttonOpenFileActionPerformed

    private void showHelp(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_showHelp
        String helpMessage = "SeamCarving v4\n" +
                "(c) 2007 by Mathias Lux\n" +
                "mathias@juggle.at\n" +
                "http://www.semanticmetadata.net\n\n" +
                "License: GNU GPL\n" +
                "Source available @ http://www.semanticmetadata.net";
        JOptionPane.showMessageDialog(this, helpMessage, "About ImageSeams", JOptionPane.INFORMATION_MESSAGE);
    }//GEN-LAST:event_showHelp

    public int getBrushSize() {
        return brushSizeSlider.getValue();
    }

    /**
     * @param args the command line arguments
     */
    public static void main(String args[]) {
        try {
            UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
        } catch (ClassNotFoundException e) {
            e.printStackTrace();  //To change body of catch statement use File | Settings | File Templates.
        } catch (InstantiationException e) {
            e.printStackTrace();  //To change body of catch statement use File | Settings | File Templates.
        } catch (IllegalAccessException e) {
            e.printStackTrace();  //To change body of catch statement use File | Settings | File Templates.
        } catch (UnsupportedLookAndFeelException e) {
            e.printStackTrace();  //To change body of catch statement use File | Settings | File Templates.
        }
        java.awt.EventQueue.invokeLater(new Runnable() {
            public void run() {
                new SeamCarvingFrame().setVisible(true);
            }
        });
    }

    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JLabel brushSizeLabel;
    private javax.swing.JSlider brushSizeSlider;
    private javax.swing.JButton buttonExit;
    private javax.swing.JButton buttonOpenFile;
    private javax.swing.JButton buttonProcess;
    private javax.swing.JButton buttonSaveFile;
    private javax.swing.JSpinner heightSpinner;
    private javax.swing.JButton helpButton;
    private net.semanticmetadata.seams.ImageViewPanel imagePanel;
    private javax.swing.JLabel jLabel1;
    private javax.swing.JLabel jLabel2;
    private javax.swing.JLabel jLabel3;
    private javax.swing.JScrollPane jScrollPane1;
    private javax.swing.JToolBar.Separator jSeparator1;
    private javax.swing.JToolBar.Separator jSeparator2;
    private javax.swing.JCheckBox removeCheckBox;
    private javax.swing.JToolBar toolBar;
    private javax.swing.JSpinner widthSpinner;
    // End of variables declaration//GEN-END:variables

}
